package com.qf.business.hotel.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.qf.business.hotel.service.CCityService;
import com.qf.common.core.utils.PinyinUtils;
import com.qf.data.entity.hotel.CCity;
import com.qf.data.entity.hotel.vo.CityVo;
import com.qf.data.mapper.hotel.CCityDao;
import org.springframework.aop.framework.AopContext;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.AsyncResult;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.util.concurrent.ListenableFuture;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.concurrent.CountDownLatch;
import java.util.stream.Collectors;

/**
 * (CCity)表服务实现类
 *
 * @author makejava
 * @since 2021-10-19 15:56:04
 */
@Service
public class CCityServiceImpl extends ServiceImpl<CCityDao, CCity> implements CCityService {

    /**
     * 保存城市
     * @param entity
     * @return
     */
    @Override
    public boolean save(CCity entity) {
        //手动生成城市拼音
        if (StringUtils.isEmpty(entity.getCityPinyin())) {
            String pinyin = PinyinUtils.str2Pinyin(entity.getCityName());
            entity.setCityPinyin(pinyin);
        }
        return super.save(entity);
    }

    /**
     * 前端查询所有城市列表 - 同步
     * @return
     */
//    @Override
//    public List<CityVo> frontQueryAll() {
//
//        //查询城市列表
//        List<CCity> cityList = super.list();
//
//
//        //集合的转换
//        Map<String, List<CityVo>> map = cityList.stream()
//                .map(cCity -> new CityVo()
//                        .setCityName(cCity.getCityName())
//                        .setCityPinYin(cCity.getCityPinyin())
//                        .setCityPY(cCity.getCityPinyin()))
//                .collect(Collectors.toMap(
//                        cityVo -> cityVo.getCityPinYin().substring(0, 1),
//                        cityVo -> {
//                            List list = new ArrayList();
//                            list.add(cityVo);
//                            return list;
//                        },
//                        (o, o2) -> {
//                            System.out.println(o);
//                            System.out.println(o2);
//                            o.addAll(o2);
//                            return o;
//                        }, () -> new TreeMap<>()));
//
//
//        //最终转换的结果
//        //CityVo（A）
//        //CItyVo (安阳)
//        //CityVo (安庆)
//        //CityVo （B）
//        //.....
//        List<CityVo> cityVos = new ArrayList<>();
//        for (Map.Entry<String, List<CityVo>> entry : map.entrySet()) {
//            //获取当前的首字母
//            String pinyin = entry.getKey();
//            //将首字母转换成CityVo对象，放入CityVoList集合中
//            cityVos.add(new CityVo().setCityName(pinyin.toUpperCase()).setCityPinYin(pinyin).setCityPY(pinyin));
//
//            //将这个首字母下的所有城市VO放入CityVoList集合中
//            cityVos.addAll(entry.getValue());
//        }
//
//        return cityVos;
//    }


    /**
     * 前端查询城市列表 - 异步
     *
     * 26个线程 ->
     * 线程1 -> 字母A
     * 线程2 -> 字母B
     * ...
     * 汇总Map<String, List<CityVo>>
     *
     * 主线程 Map转换List<CityVo> 返回
     *
     * @return
     */
    @Override
    public List<CityVo> frontQueryAll() {
        System.out.println("Service当前线程：" + Thread.currentThread().getName());

        //Map集合 key - 首字母  value - 首字母下的所有城市
        Map<String, List<CityVo>> cityVoMap = new TreeMap<>();

        //线程的计数器
        CountDownLatch countDownLatch = new CountDownLatch(26);

        //循环26个字母
        for(int i = 97; i < 123; i++){
            //转成char
            char c = (char) i;

            //调用异步方法获取拼音的城市
//            List<CityVo> cityVos = this.queryCitysByPinyin(c + "");
            //实在想要在Service中调用同类的方法
            ListenableFuture<List<CityVo>> future = ((CCityServiceImpl)AopContext.currentProxy()).queryCitysByPinyin(c + "");
            future.addCallback(result -> {
//                System.out.println("Futrue成功的回调：" + Thread.currentThread().getName());
                //成功的回调 - 子线程中执行
                if (!CollectionUtils.isEmpty(result)) {
                    cityVoMap.put(c + "", result);
                }
                //线程计数器+1
                countDownLatch.countDown();
            }, ex -> {
                //失败的回调 - 子线程中执行
            });
        }

        //主线程进行等待
        try {
            countDownLatch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        //统一转换 Map -> List<CityVo>
        System.out.println(Thread.currentThread().getName() + "主线程开始转换Map集合！！！");
        List<CityVo> cityVos = new ArrayList<>();
        for (Map.Entry<String, List<CityVo>> entry : cityVoMap.entrySet()) {
            //获取当前的首字母
            String pinyin = entry.getKey();
            //将首字母转换成CityVo对象，放入CityVoList集合中
            cityVos.add(new CityVo().setCityName(pinyin.toUpperCase()).setCityPinYin(pinyin).setCityPY(pinyin));
            //将这个首字母下的所有城市VO放入CityVoList集合中
            cityVos.addAll(entry.getValue());
        }
        System.out.println(Thread.currentThread().getName() + "主线程转换的结果：" + cityVos);
        return cityVos;
    }

    @Async
    public ListenableFuture<List<CityVo>> queryCitysByPinyin(String c){
        //获取对应字母的城市列表
        List<CityVo> cityVos = super.query()
                .likeRight("city_pinyin", c + "")
                .list()
                .stream()
                .map(cCity -> new CityVo()
                        .setCityName(cCity.getCityName())
                        .setCityPinYin(cCity.getCityPinyin())
                        .setCityPY(cCity.getCityPinyin()))
                .collect(Collectors.toList());

        System.out.println(c + "子线程获取结果：" + cityVos + " 线程名称：" + Thread.currentThread().getName());
        return new AsyncResult(cityVos);
    }


}
